package czk.concrent.safepoint;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * @Author:ChenZhangKun
 * @Date: 2022/9/8 10:52
 */
public class MainTest {
    public static AtomicInteger num = new AtomicInteger(0);

    public static void main(String[] args) throws InterruptedException {
        //  test1();
        test2();
    }

    /**
     * * 1.启动了两个长的、不间断的循环（内部没有安全点检查）。
     * * 2.主线程进入睡眠状态 1 秒钟。
     * * 3.在1000 ms之后，JVM尝试在Safepoint停止，以便Java线程进行定期清理，但是直到可数循环完成后才能执行此操作。
     * * 4.主线程的 Thread.sleep 方法从 native 返回，发现安全点操作正在进行中，于是把自己挂起，直到操作结束。
     *
     * @throws InterruptedException
     */
    public static void test1() throws InterruptedException {
        Runnable runnable = () -> {
            // 可数循环，里面不会设置安全点，会等循环结束设置安全点
            for (int i = 0; i < 1000000000; i++) {
                num.getAndAdd(1);
            }
            System.out.println(Thread.currentThread().getName() + "执行结束!");
        };

        Thread t1 = new Thread(runnable);
        Thread t2 = new Thread(runnable);
        t1.start();
        t2.start();
        // native方法，每次返回会检查设置线程安全点，此时发现发现安全点操作正在进行中，于是把自己挂起，直到操作结束。
        Thread.sleep(1000);
        System.out.println("main结束");
    }

    public static void test2() throws InterruptedException {
        Runnable runnable = () -> {
            // 不可数循环，里面不会设置安全点，再循环
            for (long i = 0; i < 1000000000; i++) {
                num.getAndAdd(1);
            }
            System.out.println(Thread.currentThread().getName() + "执行结束!");
        };

        Thread t1 = new Thread(runnable);
        Thread t2 = new Thread(runnable);
        t1.start();
        t2.start();
        // native方法，每次返回会检查设置线程安全点。
        Thread.sleep(1000);
        System.out.println("main结束");
    }
}
